home *** CD-ROM | disk | FTP | other *** search
- /*
- 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
- | | | | | | | | | |
-
- */
-
- /*
- ** PlayFromFile
- **
- ** This module contains the routines that impliment the play from file options.
- **
- ** (NMD) 9//91 created
- ** (NMD) 10/14/91 ReadProc - moved all reads out of the code into this routine:
- ** facilitates putting other types of reads in (ex. ADSP instead
- ** of File System based)
- ** (NMD) 10/15/91 ProcessingProc - Added twos to offset conversion.
- ** (NMD) 11/10/91 BackReadProc - implimented the "Play Backwards" routines.
- */
-
-
- #pragma load "MacHeaders"
-
-
- #ifndef __MAININCLUDES__
- #include "MainApp.h"
- #endif
-
- #ifndef __DOUBLEBUFFERINCLUDES__
- #include "DoubleBuffer.h"
- #endif
-
- extern SndChannelPtr gSndChan;
-
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- // High Level routine for playing a file
- OSErr PlayFile(Boolean foreward, Ptr *privateData)
- {
- OSErr err = noErr;
- SFTypeList fTypes;
- StandardFileReply sReply;
- short fRefNum;
- unsigned long playLength = 0;
- long dataOffset = 0;
- SoundHeader tempHeader;
-
-
- // We're only interested in AIFF files showing up in the standard file dialog; set
- // the type list accordingly.
- fTypes[0] = AIFFID;
-
- StandardGetFile (NULL, 1, fTypes, &sReply);
- if (sReply.sfGood) {
-
- err = FSpOpenDF (&sReply.sfFile, fsRdPerm, &fRefNum);
- if (err == noErr) {
-
- playLength = GetAIFFHeaderInfo(fRefNum, &tempHeader); // Get Header & sound len
- err = GetFPos (fRefNum,&dataOffset);
-
- if (playLength != 0) {
- if (foreward)
- err = DoubleBuffer(gSndChan, fRefNum, (ProcPtr)ReadProc, (ProcPtr)ProcessingProc,
- &tempHeader, playLength, dataOffset, privateData);
- else
- err = DoubleBuffer(gSndChan, fRefNum, (ProcPtr)BackReadProc,
- (ProcPtr)BackProcessingProc,&tempHeader, playLength, dataOffset, privateData);
- }
- }
- }
- return (err);
- }
-
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- // Pre-fills each of the buffers
- OSErr PrimeBuffers (PrivateDBInfoPtr dbInfo, SoundHeaderPtr generalHeader)
- {
- OSErr err = noErr; // error bucket
- long actualBytes = kBufferSize; // bytes (to) read
- short index = 0; // index for buffer elements
- short headerOffset = 0;
-
- headerOffset = sizeof(dbInfo->buffers[index].header->samplePtr) + // don't step on full header
- sizeof(dbInfo->buffers[index].header->length);
-
- for (index = 0; index < kNumBuffers; index++) {
- DebugMessage ("\pabout fill header's buffer");
-
- // Make a copy of the header
- BlockMove ((Ptr)generalHeader+headerOffset, (Ptr)dbInfo->buffers[index].header+headerOffset,
- sizeof (SoundHeader)-headerOffset);
-
- err = (*(dbInfo->readProcPtr)) (dbInfo, index, false); // fill the buffer...
-
- switch (err) {
- case noErr: // Happy - movin' on
- if (dbInfo->processingProcPtr)
- CallDTWithParam (dbInfo->processingProcPtr,
- &(dbInfo->buffers[index]));
- break;
-
- case eofErr: // EEK: ran out of file!
- Assert (true, "\pHit EOF trying to fill thisHeader");
- if (dbInfo->processingProcPtr)
- CallDTWithParam (dbInfo->processingProcPtr, &(dbInfo->buffers[index]));
- dbInfo->bytesToGo = 0; // we be out 'o data
- err = noErr; // not really an error
- break; // don't *need* this
-
- default: // EEK: got a BAD error!
- Assert (true, "\pGot a really bad error trying to fill a header");
- }
- }
- return (err); // Happy: bye-bye
- }
-
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- // read procedure for retrieving sound data from the file
- OSErr ReadProc (void *private, short bufNum, Boolean asynch)
- {
- OSErr err = noErr;
- long oldA5 = nil;
- long rdSize = 0;
- register strippedDownReadPBPtr pb = nil;
- PrivateDBInfoPtr dbInfo;
-
- dbInfo = (PrivateDBInfoPtr) private;
-
- if (dbInfo->bytesToGo == 0) // No Bytes to read? bail
- err = eofErr;
- else {
-
- // Again, optimizing out some of these de-references
- pb = &(dbInfo->buffers[bufNum].readPB.pb);
-
- if (dbInfo->bytesToGo > kBufferSize)
- rdSize = kBufferSize;
- else
- rdSize = dbInfo->bytesToGo;
-
- pb->ioFRefNum = dbInfo->refNum; // set up the paramBlock
- pb->ioBuffer = dbInfo->buffers[bufNum].header->samplePtr;
- pb->ioReqCount = rdSize;
- pb->ioPosMode = fsAtMark;
- pb->ioPosOffset =0;
- dbInfo->buffers[bufNum].readPB.userInfo = (Ptr)dbInfo;
- dbInfo->buffers[bufNum].readPB.headerNum = bufNum;
-
- if (asynch)
- pb->ioCompletion = (ProcPtr)&CompleteRead;
- else
- pb->ioCompletion = nil;
-
- err = PBRead ((ParmBlkPtr)pb, asynch);
- Assert (err, "\p(ReadProc) croaked queueing read ;g");
-
- dbInfo->bytesToGo -= rdSize;
-
- if (!asynch) {
- dbInfo->buffers[bufNum].header->length = pb->ioActCount;
-
- // if we were called synchronously, chances are we care about the when we hit the
- // "End of File", so if rdSize is less than the buffersize we know this was the
- // last buffer read...
- if (rdSize < kBufferSize)
- err = eofErr;
- }
- }
- return (err);
- }
-
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- void ProcessingProc (void)
- {
- SampleBufferPtr bufPtr;
-
- bufPtr = getDTParam(); // retrieve sample info
-
- TwosToOffset (bufPtr->header->samplePtr, bufPtr->header->length);
-
- bufPtr->flags = kBufferReady;
- }
-
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- // read procedure used for playing a file backwards. Starts reading from the
- // end of file and moves toward the beginning of file.
- OSErr BackReadProc (void *private, short bufNum, Boolean asynch)
- {
- OSErr err = noErr;
- long oldA5 = nil;
- long rdSize = 0;
- register strippedDownReadPBPtr pb = nil;
- PrivateDBInfoPtr dbInfo;
-
- dbInfo = (PrivateDBInfoPtr) private;
-
- if (dbInfo->bytesToGo == 0) // No Bytes to read? bail
- err = eofErr;
- else {
-
- // Again, optimizing out some of these de-references
- pb = &(dbInfo->buffers[bufNum].readPB.pb);
-
- if (dbInfo->bytesToGo > kBufferSize)
- rdSize = kBufferSize;
- else
- rdSize = dbInfo->bytesToGo;
-
- pb->ioFRefNum = dbInfo->refNum; // set up the paramBlock
- pb->ioBuffer = dbInfo->buffers[bufNum].header->samplePtr;
- pb->ioReqCount = rdSize;
- pb->ioPosMode = fsFromStart;
- pb->ioPosOffset =dbInfo->fileDataStart + dbInfo->bytesToGo - rdSize;
- dbInfo->buffers[bufNum].readPB.userInfo = (Ptr)dbInfo;
- dbInfo->buffers[bufNum].readPB.headerNum = bufNum;
-
- if (asynch == true)
- pb->ioCompletion = (ProcPtr)&CompleteRead;
- else
- pb->ioCompletion = nil;
-
- err = PBRead ((ParmBlkPtr)pb, asynch);
- Assert ((err != noErr), "\p(ReadProc) croaked queueing read ;g");
-
- dbInfo->bytesToGo -= rdSize;
-
- if (!asynch) {
- dbInfo->buffers[bufNum].header->length = pb->ioActCount;
-
- // if we were called synchronously, chances are we care about the when we hit the
- // "End of File", so if rdSize is less than the buffersize we know this was the
- // last buffer read...
- if (rdSize < kBufferSize)
- err = eofErr;
- }
- }
- return (err);
- }
-
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- // processing procedure used when playing a file backwards
- void BackProcessingProc (void)
- {
- SampleBufferPtr bufPtr;
-
- bufPtr = getDTParam(); // retrieve sample info
-
- Reverse (bufPtr->header->samplePtr, bufPtr->header->length);
-
- bufPtr->flags = kBufferReady;
- }
-
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- // convert the buffer from "twos complimentary" into "offset binary"
-
- void TwosToOffset (Ptr buffer,long length)
- {
- short i;
-
- // divide the length by four (by shifting right) to find the number of long words
- for (i = (length >> 2) - 1; i >= 0; --i)
- * ((long *)buffer)++ ^= 0x80808080;
-
- // do the remaining number of bytes (by ANDing to get the two least significant bits)
- for (i = (length & 3) - 1; i >= 0; --i)
- * (char *)buffer++ ^= 0x80;
-
- }
-
- //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- // reverse all the bytes in the buffer, and convert them to offset-binary
- void Reverse (char *buffer, long length)
- {
- short i;
- unsigned char *endBuffer;
- unsigned char *startBuffer = buffer;
- unsigned char saveByte;
- unsigned char mask = 0x80;
-
- endBuffer = (buffer + length);
- for (i = (length >> 1) - 1; i >= 0; --i) {
- saveByte = *--endBuffer;
- *endBuffer = *startBuffer;
- *startBuffer = saveByte;
- *endBuffer ^= mask;
- *startBuffer++ ^= mask;
- }
-
- // if there is an exact mid-point then the length is odd
- // at this stage the pointer will be at the middle byte
- if (length & 1)
- *startBuffer ^= mask;
- }
-